# -*- coding: utf-8 -*-
# created on 2016/11/30
import copy

from mathsolver.functions.mathematica.mathematicaSolve import MathematicaSolve
from mathsolver.functions.shulie.Fundamental import *
from mathsolver.functions.base import *
from mathsolver.functions.shulie.ShuLie_Transform import DengChaBiExprNormalization
from mathsolver.functions.shulie.ShuLie_getSeqPoly import ShuLieGetSeqPoly


class ShuLieTOFSeqEq001(BaseFunction):
    def solver(self, *args):
        assert len(args) == 1
        assert isinstance(args[0], BaseSeqEq)
        left, right = args[0].sympify()
        expr = left - right
        known = dict(self.known)
        stepsolver = ShuLieGetSeqPoly(known).solver(BasePoly(expr))
        values = stepsolver.output[0].sympify()
        assert len(values) == 1
        minus = values[0]
        if minus == 0:
            self.output.append(BaseBool(True))
        else:
            self.output.append(BaseBool(False))
        return self


# 如果数列{a_{n}}是等差数列,则( ) a_{1}+a_{8}=a_{4}+a_{5}
class ShuLieTOFSeqEq002(BaseFunction):
    def solver(self, *args):
        assert len(args) == 1
        assert isinstance(args[0], BaseSeqEq)
        known = self.known
        assert 'Sequations' not in known
        left, right = args[0].sympify()
        expr = left - right
        expr_xiangs = sl_xiangs(expr)
        assert expr_xiangs
        for expr_xiang in expr_xiangs:
            new_item = sympify(expr_xiang)
            new_item_name = new_item.func
            sl = self.search(str(new_item_name))
            assert sl
            sl_type = sl.type
            assert sl_type == "DengCha" or sl_type == "DengBi"
            stepsolver = DengChaBiExprNormalization(known).solver(BaseSeqPoly(new_item))
            new_item_value = stepsolver.output[0].sympify()
            expr = expr.subs({new_item: new_item_value})

        if expr == S.Zero:
            self.output.append(BaseBool(True))
        else:
            self.output.append(BaseBool(False))
        return self


# 如果a_{1},a_{2},…,a_{8}为各项都大于零的等差数列,公差d≠0,则( ) a_{1}*a_{8}=a_{4}*a_{5}
class ShuLieTOFSeqEq003(BaseFunction):
    def solver(self, *args):
        assert len(args) == 1
        assert isinstance(args[0], BaseSeqEq)
        known = self.known
        assert 'Sequations' in known
        new_seqs = known['Sequations']
        answer = True
        for eq in new_seqs:
            if len(eq) == 2:
                answer = False
                break
        assert answer
        left, right = args[0].sympify()
        expr = left - right
        expr_xiangs = sl_xiangs(expr)
        assert expr_xiangs
        for expr_xiang in expr_xiangs:
            new_item = sympify(expr_xiang)
            new_item_name = new_item.func
            sl = self.search(str(new_item_name))
            assert sl
            sl_type = sl.type
            assert sl_type == "DengCha" or sl_type == "DengBi"
            stepsolver = DengChaBiExprNormalization(known).solver(BaseSeqPoly(new_item))
            new_item_value = stepsolver.output[0].sympify()
            expr = expr.subs({new_item: new_item_value})
        expr = expr.expand().simplify()
        new_seqs.append([expr, S.Zero])
        solutions = MathematicaSolve().solver(BaseIneqs(new_seqs)).output[0].sympify()
        solutions_keys = solutions.keys()
        assert len(solutions_keys) == 1
        solutions_key = solutions_keys[0]
        solutions_value = solutions[solutions_key]
        if not solutions_value:
            self.output.append(BaseBool(False))
        else:
            self.output.append(BaseBool(True))
        return self


class ShuLieTOFSeqEq(BaseFunction):
    CLS = [ShuLieTOFSeqEq001, ShuLieTOFSeqEq002, ShuLieTOFSeqEq003]

    def solver(self, *args):
        known = self.known
        r = None
        for cl in ShuLieTOFSeqEq.CLS:
            try:
                new_known = copy.deepcopy(known)
                r = cl(known=new_known, verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r
